﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.NetworkInformation;
using System.Net;

#endregion


namespace ESF.General
{
	public static class TcpHelper
	{
		public static IPEndPoint CheckAvailable (IPEndPoint pEndPoint)
		{
			return CheckAvailable (pEndPoint, false);
		}


		public static IPEndPoint CheckAvailable (IPEndPoint pEndPoint, bool pAllowSearchPort)
		{
			FindNextAvailablePort (pEndPoint.Port, pAllowSearchPort);

			return pEndPoint;
		}
		

		/// <summary>
		/// Check if startPort is available, incrementing and
		/// checking again if it's in use until a free port is found
		/// </summary>
		/// <param name="pStartPort">The first port to check</param>
		/// <returns>The first available port</returns>
		public static int FindNextAvailablePort (int pStartPort)
		{
			return FindNextAvailablePort (pStartPort);
		}
		
		
		public static int FindNextAvailablePort (int pStartPort, bool pAllowSearchPort)
		{
			int port = pStartPort;
			bool isAvailable = true;

			IPGlobalProperties ipGlobalProperties;
			IPEndPoint [] endPoints;

			Mutex mutex;
			
			
			mutex = new Mutex(false, string.Concat("Global/", Guid.NewGuid ().ToString ()));

			mutex.WaitOne();

			try
			{
				ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
				endPoints = ipGlobalProperties.GetActiveTcpListeners();

				do
				{
					if (!isAvailable)
					{
						port++;
						isAvailable = true;
					}

					foreach (IPEndPoint endPoint in endPoints)
					{
						if (endPoint.Port != port) 
						{
							continue;
						}

						isAvailable = false;
						break;
					}

					if (!pAllowSearchPort)
					{
						break;
					}

				} while (!isAvailable && port < IPEndPoint.MaxPort);

				if (!isAvailable)
				{
					throw new GenericException (GenericException.PREFIX_CRITICAL_ERROR + "NOAVAILABLEPORTS", string.Format ("No fueron encontrados puertos libres a partir del {0}", pStartPort));
				}

				return port;
			}
			finally
			{
				mutex.ReleaseMutex();
			}
		}
	}
}
